package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.jxc.abstracts.AbstractJxcAddDataService;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PaySheetTypeEnum;
import com.xbongbong.paas.enums.SheetTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.vo.FormDataAddVO;
import com.xbongbong.paas.service.dynamic.help.DynamicHelp;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.FormDataUtil;
import com.xbongbong.parent.pojo.AddValidateReturnPojo;
import com.xbongbong.pro.enums.errorcodes.BuinessDefaultErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.vo.BeforeSaveVO;
import com.xbongbong.pro.formdata.pojo.vo.SaveVO;
import com.xbongbong.pro.sheet.pojo.SheetAttrPojo;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.domain.entity.PayPlanSheetSubDataEntity;
import com.xbongbong.saas.domain.entity.ext.PayPlanSheetEntityExt;
import com.xbongbong.saas.enums.SheetAloneEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.help.FundHelp;
import com.xbongbong.saas.model.PaasFormSubDataModel;
import com.xbongbong.saas.model.PayPlanSheetModel;
import com.xbongbong.saas.model.PayPlanSheetSubDataModel;
import com.xbongbong.saas.service.PayPlanSheetService;
import com.xbongbong.saas.service.toolbox.help.SaasSaveHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

/**
 *
 * @author 魏荣杰
 * @date 2021/1/4 16:29
 * @since
 * @version
 */
@Service("paySheetFormDataServiceImpl")
public class PaySheetFormDataServiceImpl extends AbstractJxcAddDataService {

    private static final Logger LOG = LoggerFactory.getLogger(PaySheetFormDataServiceImpl.class);
    @Resource
    private PayPlanSheetService payPlanSheetService;

    @Resource
    private PaasFormSubDataModel paasFormSubDataModel;
    @Resource
    private PayPlanSheetModel payPlanSheetModel;
    @Resource
    private FundHelp fundHelp;
    @Resource
    private DynamicHelp dynamicHelp;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private SaasSaveHelper saasSaveHelper;
    @Resource
    private PayPlanSheetSubDataModel payPlanSheetSubDataModel;

    @Override
    public List<Integer> businessList() {
        return Arrays.asList(XbbRefTypeEnum.PAY_SHEET.getCode(),XbbRefTypeEnum.PREPAY.getCode(),
        XbbRefTypeEnum.WRITE_OFF_PREPAY.getCode(),
        XbbRefTypeEnum.RED_WRITE_OFF_PAY.getCode(),
        XbbRefTypeEnum.RED_WRITE_OFF_PREPAY.getCode(),
        XbbRefTypeEnum.RED_PREPAY.getCode(),
        XbbRefTypeEnum.BAD_PAY.getCode(),
        XbbRefTypeEnum.PREPAY_BALANCE.getCode());
    }

    @Override
    public PaasFormEntityExt getFormEntity(FormDataAddDTO formDataAddDTO) throws XbbException {
        Integer businessType = formDataAddDTO.getBusinessType();
        if (Objects.equals(businessType, XbbRefTypeEnum.PREPAY_BALANCE.getCode())) {
            // 预付款 特殊逻辑
            XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.PAY_SHEET;
            businessType = XbbRefTypeEnum.PREPAY.getCode();
            String corpid = formDataAddDTO.getCorpid();
            PaasFormEntityExt paasFormEntityExt = paasFormModel.getByBusinessType(xbbRefTypeEnum.getCode(), corpid);
            if ( paasFormEntityExt == null ) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
            }
            formDataAddDTO.setBusinessType(businessType);
            formDataAddDTO.setSubBusinessType(businessType);
            formDataAddDTO.setFormId(paasFormEntityExt.getId());
            formDataAddDTO.setMenuId(paasFormEntityExt.getMenuId());
            formDataAddDTO.setAppId(paasFormEntityExt.getAppId());
            return paasFormEntityExt;
        }
        return paasFormModel.getByKey(formDataAddDTO.getFormId(), formDataAddDTO.getCorpid());
    }

    @Override
    public AddValidateReturnPojo analyticalData(FormDataAddDTO formDataAddDTO, ValidateDataDTO validateDataDTO, Map<String, FieldAttrEntity> explainMap) throws XbbException {
        // 将dataList的amountDetail获取出并放到dto中，最终会存放到dto的saasNeedRedundantAttrPoJo的amountDetail中
        Integer businessType = formDataAddDTO.getBusinessType();
        SheetTypeEnum sheetTypeEnum = SheetTypeEnum.getByBusinessType(businessType);
        JSONArray amountDetail = saasSaveHelper.getAmountDetail4Check(null, sheetTypeEnum, formDataAddDTO.getDataList(), businessType);
        validateDataDTO.setAmountDetail(amountDetail);
        return super.analyticalData(formDataAddDTO, validateDataDTO, explainMap);
    }


    @Override
    public SaveVO save(FormDataAddDTO formDataAddDTO, BeforeSaveVO beforeSaveVO, PaasFormEntityExt paasFormEntity, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        Long dataId = 0L;
        String corpid = formDataAddDTO.getCorpid();
        Integer saasMark = formDataAddDTO.getSaasMark();
        Integer businessType = formDataAddDTO.getBusinessType();
        Long refundId = null;
        try {
            UserVO userVO = getUserName(formDataAddDTO, paasFormDataEntity);
            Integer noApprovalRequired = beforeSaveVO.getNoApprovalRequired();
            if (Objects.equals(1, noApprovalRequired)) {
                JSONObject data = paasFormDataEntity.getData();
                refundId = data.getLong(PaasConstant.RETURNED_PURCHASE_ID);
                FormDataUtil.removeSystemData(data);
                Object richTextData = removeRichText(data);
                String uuid = UUID.randomUUID().toString();
                paasFormDataEntity.setUuid(uuid);
                PaySheetTypeEnum paySheetTypeEnum = PaySheetTypeEnum.getByBusinessType(businessType);
                SheetTypeEnum sheetTypeEnum = paySheetTypeEnum.getSheetTypeEnum();
                SheetAttrPojo sheetAttrPojo = new SheetAttrPojo(sheetTypeEnum.getXbbRefTypeEnum());
                fundHelp.formatAmountWriteOff(null, sheetTypeEnum, sheetAttrPojo, data);
                PayPlanSheetEntityExt payPlanSheetEntityExt = new PayPlanSheetEntityExt();
                BeanUtil.copyProperties(paasFormDataEntity, payPlanSheetEntityExt);
                JSONArray amountArray;
                if (Objects.nonNull(formDataAddDTO.getAmountDetail())) {
                    // 审批进来的合并付款
                    amountArray = formDataAddDTO.getAmountDetail();
                } else {
                    amountArray = beforeSaveVO.getSaasNeedRedundantAttrPojo().getAmountDetail();
                }
                if (Objects.nonNull(amountArray) && amountArray.size() > BasicConstant.ONE) {
                    payPlanSheetEntityExt.setAlone(SheetAloneEnum.PARENT.getCode());
                } else {
                    //没有明细，父子合并
                    payPlanSheetEntityExt.setAlone(SheetAloneEnum.NORMAL.getCode());
                }

                // 去除无用字段，不然入es失败 @date 2021/10/11 15:59
                payPlanSheetEntityExt.getData().remove(PaasConstant.RETURNED_PURCHASE_ID);
                payPlanSheetModel.insert(payPlanSheetEntityExt);
                dataId = payPlanSheetEntityExt.getDataId();
                paasFormSubDataModel.transferSubForm(payPlanSheetEntityExt, IndexTypeEnum.IDX_SAAS_PAYPLAN_SHEET_SUB);
                // 设置属性用于返回
                setPartialAttributes(dataId, payPlanSheetEntityExt.getSubFormData(), payPlanSheetEntityExt.getData(), payPlanSheetEntityExt.getAddTime(),
                        payPlanSheetEntityExt.getUpdateTime(), paasFormDataEntity, beforeSaveVO);
                //文件柜数据保存
                saveFile(formDataAddDTO, paasFormDataEntity, userVO);
                //富文本数据保存
                saveRichText(formDataAddDTO, paasFormDataEntity, richTextData);
                }
            return new SaveVO(noApprovalRequired, paasFormDataEntity, dataId, userVO, refundId);
        } catch (Exception e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200018);
        }
    }

    @Override
    public void saveRollBack(Long id, String corpid, Integer saasMark, Integer businessType) throws XbbException {
        if (id == null || id == 0 || corpid == null || saasMark == null) {
            return ;
        }
        IndexTypeEnum indexTypeEnum = getIndexTypeEnum(corpid, saasMark, businessType);
        //删除主表es数据
        physicalDeleteFormData(id, corpid, indexTypeEnum);
        // 子表单的删除
        List<PayPlanSheetSubDataEntity> bomBillSubDataEntities = payPlanSheetSubDataModel.getByDataId(id, corpid);
        if (CollectionsUtil.isNotEmpty(bomBillSubDataEntities)) {
            physicalDeleteSubBatch(corpid, bomBillSubDataEntities, IndexTypeEnum.IDX_SAAS_PAYPLAN_SHEET_SUB);
        }
    }

    @Override
    public FormDataAddVO afterSave(FormDataAddDTO formDataAddDTO, BeforeSaveVO beforeSaveVO, SaveVO saveVO, PaasFormEntityExt paasFormEntity, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        FormDataAddVO formDataAddVO = new FormDataAddVO();
        Long dataId = saveVO.getDataId();
        String corpid = formDataAddDTO.getCorpid();
        Integer saasMark = formDataAddDTO.getSaasMark();
        Integer businessType = formDataAddDTO.getBusinessType();
        try {
            if (Objects.equals(1, saveVO.getNoApprovalRequired())) {
                SaasFormSaveDTO saasFormSaveDTO = new SaasFormSaveDTO();
                BeanUtil.copyProperties(formDataAddDTO, saasFormSaveDTO);
                paasFormDataEntity.setId(dataId);
                packageSaasFormInsertSaveDTO(saasFormSaveDTO, paasFormDataEntity);
                saasFormSaveDTO.setSaasNeedRedundantAttrPoJo(beforeSaveVO.getSaasNeedRedundantAttrPojo());
                saasFormSaveDTO.setReturnedPurchaseId(saveVO.getRefundId());
                if (Objects.nonNull(formDataAddDTO.getAmountDetail())) {
                    // 审批进来的合并付款
                    saasFormSaveDTO.setAmountDetail(formDataAddDTO.getAmountDetail());
                } else {
                    saasFormSaveDTO.setAmountDetail(beforeSaveVO.getSaasNeedRedundantAttrPojo().getAmountDetail());
                }
                payPlanSheetService.afterSave(saasFormSaveDTO);
                // 动态处理
                dynamicHelp.addLinkData(saasFormSaveDTO);
                // api
                apiHook(formDataAddDTO, saveVO, beforeSaveVO);
                // 业务规则
                activeRule(formDataAddDTO, beforeSaveVO, saveVO.getPaasFormDataEntity(), beforeSaveVO.getPaasFormEntityExt());

                formDataAddVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_RETURN_MSG));
                formDataAddVO.setCode(PaasConstant.FORM_ADD_RETURN_CODE);
                formDataAddVO.setDataId(saveVO.getDataId());
                formDataAddVO.setFormDataId(saveVO.getDataId());
            } else {
                formDataAddVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_PROCESS_RETURN_MSG));
                formDataAddVO.setCode(PaasConstant.FORM_ADD_PROCESS_RETURN_CODE);
            }
            return formDataAddVO;
        }   catch (Exception e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200018);
        }
    }

    @Override
    public void afterSaveLog(FormDataAddDTO formDataAddDTO, PaasFormEntityExt paasFormEntityExt, PaasFormDataEntity newPaasFormDataEntity, SaveVO saveVO, BeforeSaveVO beforeSaveVO) throws XbbException {

    }

    @Override
    public void apiHook(FormDataAddDTO formDataAddDTO, SaveVO saveVO, BeforeSaveVO beforeSaveVO) throws XbbException {
        lowCodeExecuteService(formDataAddDTO, saveVO, beforeSaveVO);
    }

    @Override
    public SaveVO saveForWorkflow(FormDataAddDTO formDataAddDTO, BeforeSaveVO beforeSaveVO, PaasFormEntityExt paasFormEntity, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        Long dataId = 0L;
        String corpid = formDataAddDTO.getCorpid();
        Integer saasMark = formDataAddDTO.getSaasMark();
        Integer businessType = formDataAddDTO.getBusinessType();
        formDataAddDTO.setSubBusinessType(businessType);
        Long refundId = null;
        try {
            UserVO userVO = getUserName(formDataAddDTO, paasFormDataEntity);
            Integer noApprovalRequired = beforeSaveVO.getNoApprovalRequired();
            JSONObject data = paasFormDataEntity.getData();
            Object richTextData = removeRichText(data);
            JSONObject originData = (JSONObject) data.clone();
            FormDataUtil.removeSystemData(paasFormDataEntity.getData());
            PayPlanSheetEntityExt payPlanSheetEntityExt = new PayPlanSheetEntityExt();
            BeanUtil.copyProperties(paasFormDataEntity, payPlanSheetEntityExt);
            JSONArray amountArray;
            if (Objects.nonNull(formDataAddDTO.getAmountDetail())) {
                // 审批进来的合并付款
                amountArray = formDataAddDTO.getAmountDetail();
            } else {
                amountArray = beforeSaveVO.getSaasNeedRedundantAttrPojo().getAmountDetail();
            }
            if (Objects.nonNull(amountArray) && amountArray.size() > BasicConstant.ONE) {
                payPlanSheetEntityExt.setAlone(SheetAloneEnum.PARENT.getCode());
            } else {
                //没有明细，父子合并
                payPlanSheetEntityExt.setAlone(SheetAloneEnum.NORMAL.getCode());
            }
            String uuid = UUID.randomUUID().toString();
            paasFormDataEntity.setUuid(uuid);
            payPlanSheetEntityExt.setUuid(uuid);
            PaySheetTypeEnum paySheetTypeEnum = PaySheetTypeEnum.getByBusinessType(businessType);
            SheetTypeEnum sheetTypeEnum = paySheetTypeEnum.getSheetTypeEnum();
            SheetAttrPojo sheetAttrPojo = new SheetAttrPojo(sheetTypeEnum.getXbbRefTypeEnum());
            fundHelp.formatAmountWriteOff(null, sheetTypeEnum, sheetAttrPojo, data);
            // 去除无用字段，不然入es失败 @date 2021/10/11 15:59
            payPlanSheetEntityExt.getData().remove(PaasConstant.RETURNED_PURCHASE_ID);
            payPlanSheetModel.insert(payPlanSheetEntityExt);
            dataId = payPlanSheetEntityExt.getDataId();
            paasFormSubDataModel.transferSubForm(payPlanSheetEntityExt, IndexTypeEnum.IDX_SAAS_PAYPLAN_SHEET_SUB);
            //重新封装一下付款单信息
            fundHelp.formatAmountWriteOff(null, sheetTypeEnum, sheetAttrPojo, data);
            // 设置属性用于返回
            setPartialAttributes(dataId, payPlanSheetEntityExt.getSubFormData(), payPlanSheetEntityExt.getData(), payPlanSheetEntityExt.getAddTime(), payPlanSheetEntityExt.getUpdateTime(), paasFormDataEntity, beforeSaveVO);
            //富文本数据保存
            saveRichText(formDataAddDTO, paasFormDataEntity, richTextData);
            paasFormDataEntity.setData(originData);
            return new SaveVO(noApprovalRequired, paasFormDataEntity, dataId, userVO, refundId);
        } catch (Exception e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200018);
        }
    }

    @Override
    public FormDataAddVO afterSaveForWorkflow(FormDataAddDTO formDataAddDTO, BeforeSaveVO beforeSaveVO, SaveVO saveVO, PaasFormEntityExt paasFormEntity, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        FormDataAddVO formDataAddVO = new FormDataAddVO();
        Long dataId = saveVO.getDataId();
        String corpid = formDataAddDTO.getCorpid();
        Integer saasMark = formDataAddDTO.getSaasMark();
        Integer businessType = formDataAddDTO.getBusinessType();
        try {
            SaasFormSaveDTO saasFormSaveDTO = new SaasFormSaveDTO();
            BeanUtil.copyProperties(formDataAddDTO, saasFormSaveDTO);
            paasFormDataEntity.setId(dataId);
            packageSaasFormInsertSaveDTO(saasFormSaveDTO, paasFormDataEntity);
            payPlanSheetService.afterSaveForWorkflow(saasFormSaveDTO);

            formDataAddVO.setDataId(saveVO.getDataId());
            formDataAddVO.setFormDataId(saveVO.getDataId());
            formDataAddVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_RETURN_MSG));
            formDataAddVO.setCode(PaasConstant.FORM_ADD_RETURN_CODE);

            return formDataAddVO;
        }   catch (Exception e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200018);
        }
    }
}
